using System;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using System.Collections.Generic;
using Crainiate.Data.Persistence.Providers;
using Crainiate.Data.Persistence.Cache;

namespace Crainiate.Data.Persistence
{
	//Returns settings depending on calling .dll. 
	public class Component 
	{
		//Singleton instance
		public static readonly Component Instance = new Component();

		//Property variables
        private static ReflectionCache mReflectionCache;
        private static Dictionary<Type, bool> mAllowedTypes;
        
		#region Interface

		//Constructors
		private Component()
		{
            mReflectionCache = new ReflectionCache();
		}

        //Properties
    	public ReflectionCache ReflectionCache
		{
			get
			{
				return mReflectionCache;
			}
		}

        //Methods
        public bool IsAllowedType(Type type)
        {
            if (type.IsEnum) return true;
            if (typeof(IPersistable).IsAssignableFrom(type)) return true;

            //Create list of allowed types
            if (mAllowedTypes == null) CreateAllowedTypes();

            return mAllowedTypes.ContainsKey(type);
        }

        public static bool IsInteger(string value)
        {
            try
            {
                int convert = Convert.ToInt32(value);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static Type ResolveType(string name)
        {
            Type type = null;

            //Try load from assembly path or resource			
            //Make an array for the list of assemblies.
            Assembly[] assemblyArray = AppDomain.CurrentDomain.GetAssemblies();

            foreach (System.Reflection.Assembly assembly in assemblyArray)
            {
                if (!assembly.FullName.StartsWith("mscorlib") && !assembly.FullName.StartsWith("System"))
                {
                    type = assembly.GetType(name, false);
                    if (type != null) return type;
                }
            }
            return null;
        }

		#endregion

		#region Implementation

        private void CreateAllowedTypes()
        {
            mAllowedTypes = new Dictionary<Type, bool>();

            mAllowedTypes.Add(typeof(string), true);
            mAllowedTypes.Add(typeof(long), true);
            mAllowedTypes.Add(typeof(int), true);
            mAllowedTypes.Add(typeof(DateTime), true);
            mAllowedTypes.Add(typeof(bool), true);
            mAllowedTypes.Add(typeof(byte), true);
            mAllowedTypes.Add(typeof(short), true);
            mAllowedTypes.Add(typeof(double), true);
            mAllowedTypes.Add(typeof(float), true);
            mAllowedTypes.Add(typeof(decimal), true);
            mAllowedTypes.Add(typeof(char), true);
            mAllowedTypes.Add(typeof(System.Guid), true);

            mAllowedTypes.Add(typeof(Nullable<long>), true);
            mAllowedTypes.Add(typeof(Nullable<int>), true);
            mAllowedTypes.Add(typeof(Nullable<DateTime>), true);
            mAllowedTypes.Add(typeof(Nullable<bool>), true);
            mAllowedTypes.Add(typeof(Nullable<byte>), true);
            mAllowedTypes.Add(typeof(Nullable<short>), true);
            mAllowedTypes.Add(typeof(Nullable<double>), true);
            mAllowedTypes.Add(typeof(Nullable<float>), true);
            mAllowedTypes.Add(typeof(Nullable<decimal>), true);
            mAllowedTypes.Add(typeof(Nullable<char>), true);
            mAllowedTypes.Add(typeof(Nullable<System.Guid>), true);

            mAllowedTypes.Add(typeof(Stream), true);
        }

		#endregion
	}
}
